/**
* 演示线程同步和线程通信
*/
class ThreadDemo4 {
	static Object msg = new Object();

	static class ThreadA extends Thread {

		public void run() {
			for (int i = 0; i < 100; i++ ) {

				synchronized (msg) {
					System.out.println("水装满了");
					try {
						msg.notify();
						msg.wait(); // 进入等待并释放A线程的锁
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

	static class ThreadB extends Thread {

		public void run() {
			for (int i = 0; i < 100; i++ ) {
				synchronized (msg) {
					System.out.println("盖子拧好了");
					try {
						msg.notify();
						msg.wait(); // 进入等待并释放B线程的锁
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

	// 模拟两个线程交叉执行
	public static void test3() {
		Thread t1 = new ThreadA();
		Thread t2 = new ThreadB();
		t1.start();
		t2.start();
	}

	//模拟3个窗口卖票
	public static void test2() {
		// 抢票的关键，是同一个任务
		Runnable task = new SaleTask();

		Thread t1 = new Thread(task);
		t1.setName("1号窗口");
		t1.start();
		Thread t2 = new Thread(task);
		t2.setName("2号窗口");
		t2.start();
		Thread t3 = new Thread(task);
		t3.setName("3号窗口");
		t3.start();
	}

	// 一个售票窗口卖票
	public static void test1() {
		Thread t1 = new Thread(new SaleTask());
		t1.start();
	}

	public static void main(String[] args) {
		test3();
	}

}

class SaleTask implements Runnable {
	private int tickets = 1000;

	public synchronized void run() {
		while (true) {
			// 将存在竞争的资源，用同步锁保护起来，一次只让一个线程执行
			// 我们将这些受保护的代码，称为原子操作
			// synchronized (this) {
			String name = Thread.currentThread().getName();
			if (tickets > 0) {
				tickets--;
				System.out.println(name + "卖出一张票，车票号码：" + (1000 - tickets));
			} else {
				break;
			}
			// }

			// 让线程睡眠一下，以便其他线程抢到调度权，不然可能一个线程一次会卖很多票出去
			try {
				Thread.sleep(1);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}